#pragma once

#ifndef HEADER_FILE_ANALYZER
#define HEADER_FILE_ANALYZER

#include <string>
#include <map>
#include "boost/shared_ptr.hpp"
#include "boost/graph/adjacency_list.hpp"
#include "boost/filesystem.hpp"

/*! \file HeaderFileAnalyzer.h
	\brief Header file for HeaderFileAnalyzer class.
	
	Details.
*/

#include "Graph.h"
#include "GraphBuilder.h"
#include "AbstractFileSystemScanner.h"
#include "AbstractCycleFinderAlgorithm.h"

namespace analyzer {

	//! This is the main class used in this component.
	class HeaderFileAnalyzer
	{
	public:
		/*! \fn HeaderFileAnalyzer(void)
			\brief Constructor of class HeaderFileAnalyzer
		*/
		HeaderFileAnalyzer(void);
		
		/*! \fn HeaderFileAnalyzer(boost::shared_ptr<AbstractFileSystemScanner> fileSystemScanner, boost::shared_ptr<AbstractCycleFinderAlgorithm> cycleFinderAlgorithm)
			\brief Constructor of class HeaderFileAnalyzer with specyfied file system scanner (first argument) and cycle finder algorithm (second argument).
			\param fileSystemScanner Pointer to file system scanner object.
			\param cycleFinderAlgorithm Pointer to cycle finder algorithm.
		*/
		HeaderFileAnalyzer(boost::shared_ptr<AbstractFileSystemScanner> fileSystemScanner, boost::shared_ptr<AbstractCycleFinderAlgorithm> cycleFinderAlgorithm);
		
		/*! \fn ~HeaderFileAnalyzer(void)
			\brief Destructor of class HeaderFileAnalyzer
		*/
		~HeaderFileAnalyzer(void);

		/*! \fn boost::shared_ptr<AbstractFileSystemScanner> getFileSystemScanner(void) const
			\brief This method gets the current file system scanner.
			\return boost::shared_ptr<AbstractFileSystemScanner> Current file system scanner.
		*/
		boost::shared_ptr<AbstractFileSystemScanner> getFileSystemScanner(void) const;
	
		/*! \fn void setFileSystemScanner(boost::shared_ptr<AbstractFileSystemScanner> fileSystemScanner)
			\brief This method sets new file system scanner.
			\param fileSystemScanner Pointer for new file system scanner.
		*/
		void setFileSystemScanner(boost::shared_ptr<AbstractFileSystemScanner> fileSystemScanner);

		/*! \fn boost::shared_ptr<AbstractCycleFinderAlgorithm> getCycleFinderAlgorithm(void) const
			\brief This method gets the current cycle finder algorithm.
			\return boost::shared_ptr<AbstractCycleFinderAlgorithm> Current cycle finder algorithm.
		*/
		boost::shared_ptr<AbstractCycleFinderAlgorithm> getCycleFinderAlgorithm(void) const;
		
		/*! \fn void setCycleFinderAlgorithm(boost::shared_ptr<AbstractCycleFinderAlgorithm> cycleFinderAlgorithm)
			\brief This method sets new cycle finder algorithm.
			\param cycleFinderAlgorithm Pointer for new cycle finder algorithm.
		*/
		void setCycleFinderAlgorithm(boost::shared_ptr<AbstractCycleFinderAlgorithm> cycleFinderAlgorithm);

		/*! \fn bool getIncludeSubDirectories() const
			\brief This method returns true if algorithm is set to search inside subdirectories.
			\return bool If algorithm is set to search inside subdirectories.
		*/
		bool getIncludeSubDirectories() const;
		
		/*! \fn void setIncludeSubDirectories(bool includeSubDirectories)
			\brief This method sets if algorithm is to search inside subdirectories.
			\param includeSubDirectories True - search inside subdirectories; False - search only current directory.
		*/
		void setIncludeSubDirectories(bool includeSubDirectories);

		/*! \fn void scanDirectory(std::string directory);
			\brief This is the method implementing search for cycles inside a directory.
			\param directory Directory to search.
		*/
		void scanDirectory(std::string directory);

	protected:

		// utility methods
		void addEdges(GraphBuilder& graphBuilder, std::string vertexName, const std::vector<std::string>& dependencies);

		// private fields
		boost::shared_ptr<AbstractFileSystemScanner> fileSystemScanner;
		boost::shared_ptr<AbstractCycleFinderAlgorithm> cycleFinderAlgorithm;

		Graph* dependencyGraph;

		bool includeSubDirectories;
	};

}

#endif // HEADER_FILE_ANALYZER
